﻿#include "music.h"

#include <QUuid>
#include <QMediaPlayer>
#include <QCoreApplication>
#include <QDebug>
#include <QSqlQuery>
#include <QSqlError>


Music::Music()
    : isLike(false)
    , isHistory(false)
{}

Music::Music(QUrl url)
    : isLike(false)
    , isHistory(false)
    , musicUrl(url)
{
    // 通过读取 url对象, 获取相关信息
    // 如:歌曲名称 ,歌唱者 ,歌曲专辑 ,歌曲持续时长等

    musicId = QUuid::createUuid().toString();
    parseMediaMetaData();
}

void Music::setIsLike(bool isLike)
{
    this->isLike = isLike;
}
void Music::setIsHistory(bool isHistory)
{
    this->isHistory = isHistory;
}
void Music::setMusicName(const QString &musicName)
{
    this->musicName = musicName;
}
void Music::setSingerName(const QString &singerName)
{
    this->singerName = singerName;
}
void Music::setAlbumName(const QString &albumName)
{
    this->albumName = albumName;
}
void Music::setDuration(const qint64 duration)
{
    this->duration = duration;
}
void Music::setMusicUrl(const QUrl &url)
{
    this->musicUrl = url;
}
void Music::setMusicId(const QString &musicId)
{
    this->musicId = musicId;
}
bool Music::getIsLike() const
{
    return isLike;
}
bool Music::getIsHistory() const
{
    return isHistory;
}
QString Music::getMusicName() const
{
    return musicName;
}
QString Music::getSingerName() const
{
    return singerName;
}
QString Music::getAlbumName() const
{
    return albumName;
}
qint64 Music::getDuration() const
{
    return duration;
}
QUrl Music::getMusicUrl() const
{
    return musicUrl;
}
QString Music::getMusicId() const
{
    return musicId;
}

QString Music::getLrcPath() const
{
    // 这里,歌曲和歌词在同一文件 后缀不一样
    QString lrcPath = musicUrl.toLocalFile();// 转化为本地的路径
    lrcPath.replace(".mp3", ".lrc");
    lrcPath.replace(".flac", ".lrc");
    lrcPath.replace(".mpga", ".lrc");

    return lrcPath;
}

void Music::insertMusicToDB()
{
    // 1.检查music歌曲在数据库中是否已经存在
    QSqlQuery query;
    query.prepare("SELECT EXISTS (SELECT 1 FROM MusicInfo WHERE musicId = ?)");
    query.addBindValue(musicId);
    if(!query.exec())
    {
        qDebug() << "insertMusicToDB, 查询失败: " << query.lastError().text();
        return;
    }

    if(query.next())
    {
        bool isExists = query.value(0).toBool();
        if(isExists)
        {
            // 2.存在：不需要再插入musci对象，此时只需要将isLike和isHistory属性进行更新
            query.prepare("UPDATE MusicInfo SET isLike = ?, isHistory = ? WHERE musicId = ?");
            query.bindValue(0, isLike ? 1 : 0);
            query.bindValue(1, isHistory ? 1 : 0);
            query.bindValue(2, musicId);
            if(!query.exec())
            {
                qDebug() << "insertMusicToDB, 更新失败: " << query.lastError().text();
                return;
            }

            qDebug() << "insertMusicToDB, 更新music信息: " << musicName << " " << musicId;
        }
        else
        {
            // 3. 不存在：直接将music的属性信息插入数据库
            //              id
            //    QString musicId;
            //    QString musicName;
            //    QString singerName;
            //    QString albumName;
            //    QUrl musicUrl;
            //    qint64 duration;
            //    bool isLike;
            //    bool isHistory;

            query.prepare("INSERT INTO MusicInfo (musicId, musicName, singerName,\
                          albumName, musicUrl, duration, isLike, isHistory)\
                    VALUES(?, ?, ?, ?, ?, ?, ?, ?)");
                    query.bindValue(0, musicId);
            query.bindValue(1, musicName);
            query.bindValue(2, singerName);
            query.bindValue(3, albumName);
            query.bindValue(4, musicUrl.toLocalFile());
            query.bindValue(5, duration);
            query.bindValue(6, isLike ? 1 : 0);
            query.bindValue(7, isHistory ? 1 : 0);
            if(!query.exec())
            {
                qDebug() << "insertMusicToDB, 插入失败: " << query.lastError().text();
                return;
            }

            qDebug() << "insertMusicToDB, 插入music信息: " << musicName << " " << musicId;
        }
    }
}

void Music::parseMediaMetaData()
{
    // 解析的时候,读取的是歌曲数据, 对用读取歌曲文件我们需要用到QMediaPlayer类
    // 1.创建媒体播放器对象
    QMediaPlayer player;

    // 2.设置媒体源,依靠setMedia()方法来解析元数据
    player.setMedia(musicUrl);

    // 3. 因为setMedia不会等待音乐的加载就立马返回
    //    因此在通过mediaMeta方法获取元数据时，需要保证媒体已经添加完毕
    //    可以通过isMetaDataAvailable检测数据是否有效
    //    如果该方法返回true，说明加载完成
    while(!player.isMetaDataAvailable())
    {
        // 媒体元数据解析需要时间，只有等待解析完成之后，才能提取音乐信息，此处循环等待
        // 循环等待时：主界面消息循环就法无处理了，因此需要在等待解析期间，让消息循环继续处理
        QCoreApplication::processEvents();
    }

    // 到了这里说明已经加载完成, 开始提取有效的元数据
    if(player.isMetaDataAvailable())
    {
        //QVariant metaData():给其提供主题,它给你返回相关信息 ,返回值是通用容器
        musicName = player.metaData("Title").toString();
        singerName = player.metaData("Author").toString();
        albumName = player.metaData("AlbumTitle").toString();
        duration = player.metaData("Duration").toLongLong();

        // 一般情况下:上面的操作可以把相关的信息补充完整,但是可能有盗版音乐等因素,导致不能够使信息完整
        // 所以通过下面的操作尽量减少信息不完整(注意:通过下属操作仍存在信息不完整的情况)

        // 一般的文件名: "2002年的第一场雪 - 刀郎.mp3"
        // 也可能是:    "2002年的第一场雪.mp3"
        QString fileName = musicUrl.fileName();
        //int QString::indexOf(QChar);从0位置开始找 '-',找到了返回它的下标,否则 '-1'
        int index = fileName.indexOf('-');

        // 对于歌曲名称
        // 歌曲作者对齐处理, QString类提供了 trimmed()方法，专门用来去除字符串前后空格字符的
        if(musicName.isEmpty())
        {
            if(index != -1)
            {
                // QString QString::mid(int position, int n); 从position位置开始,截取长度为 n 的字符串
                musicName = fileName.mid(0, index).trimmed();
            }
            else
            {
                musicName = fileName.mid(0, fileName.indexOf('.')).trimmed();
            }
        }

        // 对于歌手名称
        if(singerName.isEmpty())
        {
            if(index != -1)
            {
                // QString QString::mid(int position, int n); 从position位置开始,截取长度为 n 的字符串
                singerName = fileName.mid(index + 1, fileName.indexOf('.') - index - 1).trimmed();
            }
            else
            {
                singerName = "未知歌手";
            }
        }

        // 对于专辑名称
        if(albumName.isEmpty())
        {
            albumName = "未知专辑";
        }

        qDebug() << fileName << " --- " << musicName << " --- " << singerName << " --- " << albumName << " --- " << duration;
    }
}

